<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.5"/>
<title>NDK Programmer&#39;s Guide: native-activity</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
  $(document).ready(initResizable);
  $(window).load(resizeHeight);
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td style="padding-left: 0.5em;">
   <div id="projectname">NDK Programmer&#39;s Guide
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.5 -->
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;"
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
$(document).ready(function(){initNavTree('md_2__samples_sample--nativeactivity.html','');});
</script>
<div id="doc-content">
<div class="header">
  <div class="headertitle">
<div class="title">native-activity </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>This is a very simple example of a purely native
application, with no Java source code. In the absence of any Java source, the
Java compiler still creates an executable stub for the Dalvik Virtual Machine
("DVM") to run. The stub serves as a wrapper for the actual, native program,
which lives in the .so file.</p>
<p>The application itself simply renders a color onto the entire screen, and
then changes the color partly in response to detected movement.</p>
<h3>AndroidManifest.xml</h3>
<p>Make sure not to specify an Android API level lower than 9.</p>
<pre class="fragment">&lt;uses-sdk android:minSdkVersion="9" /&gt;
</pre><p>Because this application has only native code, specify
<code>android:hasCode</code> as <code>false</code>.</p>
<pre class="fragment">&lt;application android:label="@string/app_name"
android:hasCode="false"&gt;
</pre><p>Declare the <code>NativeActivity</code> class.</p>
<pre class="fragment">    &lt;activity android:name="android.app.NativeActivity"
</pre><p>For <code>android:value</code>, provide the name of the shared library
to be built, minus the initial <code>lib</code> and the <code>.so</code>
extension. This value must be the same as the one you described for
<code>LOCAL_MODULE</code> in <code>Android.mk</code>.</p>
<pre class="fragment">        &lt;meta-data android:name="android.app.lib_name"
                android:value="native-activity" /&gt;
</pre><h3>Android.mk</h3>
<p>This file tells the build system the following information:</p>
<p>The name of the shared library to generate.</p>
<pre class="fragment">LOCAL_MODULE    := native-activity
</pre><p>The name of the native source-code file.</p>
<pre class="fragment">LOCAL_SRC_FILES := main.c
</pre><p>A list of external libraries that will be used in building the binary,
each preceded by the <code>-l</code> (link-against) option.</p>
<ul>
<li>log is a logging library.</li>
<li>android encompasses the standard Android support APIs for NDK. The <a href="./md_3__key__topics__libraries__s_t_a_b_l_e-_a_p_i_s.html">Stable APIs</a>
section discusses these in more detail.</li>
<li>EGL, standardized by Khronos, corresponds to the platform-specific portion
of the graphics API.</li>
<li>OpenGL ES, the version of OpenGL for Android, depends on EGL.</li>
</ul>
<p>Note that, for each library:</p>
<ul>
<li>The actual file name starts with <code>lib</code>, and ends with the
<code>.so</code> extension. For example, the actual file name for the
<code>log</code> library is <code>liblog.so</code>.</li>
<li>The library lives in the following directory, relative to the NDK root:
<code>&lt;ndk&gt;/platforms/android-&lt;sdk_version&gt;/arch-&lt;abi&gt;/usr/lib/</code>.</li>
</ul>
<pre class="fragment">LOCAL_LDLIBS    := -llog -landroid -lEGL -lGLESv1_CM
</pre><p>A static library, <code>android_native_app_glue</code>, that the
application uses to manage <code>NativeActivity</code> lifecycle events, along
with touch input.</p>
<pre class="fragment">LOCAL_STATIC_LIBRARIES := android_native_app_glue
</pre><p>The final line tells the build system to build this static library.
<code>ndk-build</code> places the built library
(<code>libandroid_native_app_glue.a</code>) into the <code>obj</code> directory
generated during the build process. The next sample discusses the
android_native_app_glue in more detail.</p>
<pre class="fragment">$(call import-module,android/native_app_glue)
</pre><p>For more information about the Application.mk file, consult the <a
href="./md_3__key__topics__building__a_p_p_l_i_c_a_t_i_o_n-_m_k.html">Application.mk section</a> of this guide.</p>
<h3><code>Application.mk</code></h3>
<p>This line defines the minimum level of Android API Level support.</p>
<pre class="fragment">APP_PLATFORM := android-10
</pre><p>Because there is no ABI definition, the build system defaults to
building only for armeabi.</p>
<h3>main.c</h3>
<p>This file essentially contains the entire progam.</p>
<p>The following includes correspond to the libraries, both shared and static,
enumerated in <code>Android.mk</code>.</p>
<pre class="fragment">#include &lt;EGL/egl.h&gt;
#include &lt;GLES/gl.h&gt;


#include &lt;android/sensor.h&gt;
#include &lt;android/log.h&gt;
#include &lt;android_native_app_glue&gt;
</pre><p><code>android_native_app_glue</code> calls the following function,
passing it a predefined state structure. It also serves as a wrapper that
simplifies handling of <code>NativeActivity</code> callbacks.</p>
<pre class="fragment">void android_main(struct android_app* state) {
</pre><p>Next, the program handles events queued by the glue library. The event
handler follows the state structure.</p>
<pre class="fragment">struct engine engine;


// Make sure glue isn't stripped by suppressing link-time optimization that
removes unreferenced code.
app_dummy();


memset(&amp;engine, 0, sizeof(engine));
state-&gt;userData = &amp;engine;
state-&gt;onAppCmd = engine_handle_cmd;
state-&gt;onInputEvent = engine_handle_input;
engine.app = state;
</pre><p>The application prepares to start monitoring the sensors, using the
APIs in <code>sensor.h</code>.</p>
<pre class="fragment">    engine.sensorManager = ASensorManager_getInstance();
    engine.accelerometerSensor =
                    ASensorManager_getDefaultSensor(engine.sensorManager,
                    ASENSOR_TYPE_ACCELEROMETER);
    engine.sensorEventQueue =
                    ASensorManager_createEventQueue(engine.sensorManager,
                    state-&gt;looper, LOOPER_ID_USER, NULL, NULL);
</pre><p>Now, a loop begins, in which the application polls the system for
messages (sensor events). It sends messages to
<code>android_native_app_glue</code>, which checks to see whether they match
any <code>onAppCmd</code> events defined in <code>android_main</code>. When a
match occurs, the message is sent to the handler for execution.</p>
<pre class="fragment">while (1) {
        // Read all pending events.
        int ident;
        int events;
        struct android_poll_source* source;


        // If not animating, we will block forever waiting for events.
        // If animating, we loop until all events are read, then continue
        // to draw the next frame of animation.
        while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL,
&amp;events,
                (void**)&amp;source)) &gt;= 0) {


            // Process this event.
            if (source != NULL) {
                source-&gt;process(state, source);
            }


            // If a sensor has data, process it now.
            if (ident == LOOPER_ID_USER) {
                if (engine.accelerometerSensor != NULL) {
                    ASensorEvent event;
                    while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
                            &amp;event, 1) &gt; 0) {
                        LOGI("accelerometer: x=%f y=%f z=%f",
                                event.acceleration.x, event.acceleration.y,
                                event.acceleration.z);
                    }
                }
            }


        // Check if we are exiting.
        if (state-&gt;destroyRequested != 0) {
            engine_term_display(&amp;engine);
            return;
        }
    }
</pre><p>Once the queue is empty, and the program exits the polling loop, the
program calls OpenGL to draw the screen.</p>
<pre class="fragment">    if (engine.animating) {
        // Done with events; draw next animation frame.
        engine.state.angle += .01f;
        if (engine.state.angle &gt; 1) {
            engine.state.angle = 0;
        }


        // Drawing is throttled to the screen update rate, so there
        // is no need to do timing here.
        engine_draw_frame(&amp;engine);
    }
} </pre> </div></div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
  <ul>
    <li class="footer">Generated on Wed Jun 25 2014 00:51:19 for NDK
Programmer&#39;s Guide by
    <a href="http://www.doxygen.org/index.html">
    <img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.5 </li>
  </ul>
</div>
</body>
</html>
